<template>
  <div :class="['components-chart-box', chartClass, props.bordered && 'bordered', props.theme]">
    <h4 v-if="props.title" class="chart-title" ref="titleRef">{{ props.title }}</h4>
    <div :class="['chart-container']" v-loading="loading" ref="chartRef" :style="{ height, width }">
    </div>
  </div>

</template>
<script lang="ts" setup>
import { onMounted, PropType, Ref, ref, watch, onUnmounted } from 'vue'
import { useECharts } from '@/hooks/web/useECharts'
import { EChartsOption } from 'echarts'
import { getCssVariableValue, getRandomColor, lightenColor } from '../common'

import { lineColorArr } from './data'
import '../style.scss'
import { XAXisOption } from 'echarts/types/dist/shared'

const props = defineProps({
  width: {
    type: String as PropType<string>,
    default: '100%',
  },
  height: {
    type: String as PropType<string>,
    default: '100%',
  },
  loading: {
    type: Boolean,
    default: false,
  },
  bordered: {
    type: Boolean,
    default: true,
  },
  title: {
    type: String as PropType<string>,
    default: '',
  },
  chartData: {
    type: Object as PropType<object>,
  },
  chartClass: {
    type: Object as PropType<string>,
  },
  unit: {
    type: String as PropType<string>,
    default: '',
  },
  xyDataFieldsName: {
    type: Object as PropType<{
      xDataField: string
      yDataField: string
    }>,
    default: () => ({
      xDataField: 'xaxisList',
      yDataField: 'yaxisList',
    }),
  },
  theme: {
    type: String,
    default: 'white'
  },
})

let resizeObserver: ResizeObserver | null = null

const chartRef = ref<HTMLDivElement | null>(null)
const titleRef = ref<HTMLDivElement | null>(null)
const { setOptions, echarts, resize } = useECharts(chartRef as Ref<HTMLDivElement>)
const gridLineColor = props.theme === 'dark' ? 'rgba(255,255,255,0.2)' : getCssVariableValue('--chart-grid-line-color')
const textColor = props.theme === 'dark' ? 'rgba(255,255,255,0.70)' : getCssVariableValue('--chart-text-color')

// 标题高度 + 上间距 + 标题距离 grid 间距
const gridTop = 14 + 12 + 12
const options: EChartsOption = {
  legend: {
    right: 16,
    padding: 0,
    top: 10,
    textStyle: {
      color: textColor,
    },
    icon: 'rect',
    itemWidth: 11,
    itemHeight: 2,
    // selectedMode: 'single', // 一次只能显示一个图表
  },
  grid: {
    left: '12px',
    right: '12px',
    bottom: '12px',
    top: gridTop,
    containLabel: true,
  },
  tooltip: {
    trigger: 'item',
    confine: true,
    appendToBody: true,
    className: ['echarts-line-tooltip', props.theme].join(' '),
    backgroundColor: props.theme === 'dark' ? 'rgba(50,68,121,0.5);' : '#fff',
    textStyle: {
      color: '#fff'
    },
    axisPointer: {
      type: 'shadow',
      label: {
        show: true,
        backgroundColor: '#fff',
      },
    },
    // 鼠标悬停时仅显示选中的图例
    formatter: function (params) {
      if (params.seriesName) {
        return params.seriesName + ' : ' + params.value;
      }
      return '';
    }
    // formatter: function (params: any) {
    //   return returnTooltipDom(params)
    // },
  },
  // : {
  //   // trigger: 'axis' // 鼠标放上去显示所有legend值
  //   trigger: 'item' // 鼠标放在图表上只显示一条数据
  // },
  xAxis: {
    axisLine: {
      lineStyle: {
        color: gridLineColor,
      },
    },
    axisLabel: {
      color: textColor,
    },
  },
  yAxis: {
    nameTextStyle: {
      color: textColor,
      fontSize: '12px',
    },
    splitLine: {
      lineStyle: {
        color: gridLineColor,
      },
    },
    axisLine: {
      lineStyle: {
        color: gridLineColor,
      },
    },
    axisLabel: {
      color: textColor,
    },
  },
}

onMounted(() => {
  setData()
  resizeObserver = new ResizeObserver(() => {
    resize()
  })
  if (chartRef.value) {
    resizeObserver.observe(chartRef.value as HTMLDivElement)
  }
})

onUnmounted(() => {
  if (resizeObserver && chartRef.value) {
    resizeObserver.unobserve(chartRef.value as HTMLDivElement)
  }
})

const setData = () => {
  const { xDataField, yDataField } = props.xyDataFieldsName
  if (!props.chartData || !chartRef.value) return
  const chartTitleW = titleRef.value ? titleRef.value.offsetWidth : 0
  const legendWidth = chartRef.value?.clientWidth - chartTitleW - 36
  const xData = props.chartData[xDataField]
  const yData = props.chartData[yDataField]
  if (!xData || !yData) return
  const showUnit = yData.length && props.unit
  setOptions({
    ...options,
    legend: {
      ...options.legend,
      width: legendWidth,
      data: yData.map((item) => item?.name || ''),
      type: 'scroll',
      pageTextStyle: {
        color: textColor
      }
    },
    grid: {
      ...options.grid,
      top: showUnit ? gridTop + 14 : gridTop,
    },
    xAxis: {
      ...options.xAxis,
      data: xData,
    } as XAXisOption,
    yAxis: {
      ...options.yAxis,
      name: showUnit && `单位：${props.unit}`,
    },
    series: yData.map((item, index) => {
      let colorArr = lineColorArr?.[index]

      if (!colorArr) {
        const color1 = getRandomColor()
        const color2 = lightenColor(color1)
        colorArr = [color1, color2]
      }
      return {
        ...item,
        type: 'line',
        smooth: true,
        emphasis: {
          focus: 'series'
        },
        itemStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
            { offset: 0, color: colorArr[0] },
            { offset: 1, color: colorArr[1] },
          ]),
        },
        width: 2,
      }
    }),
  })
}

watch(
  () => props.chartData,
  (val) => {
    setData()
  },
  {
    immediate: true,
  },
)

defineExpose({})
</script>
<style scoped lang="scss"></style>
<style lang="scss">
.echarts-line-tooltip {

  &.dark {
    border-color: rgb(162 193 255 / 30%) !important;

    .legend-list {
      li {
        color: #fff;
      }
    }
  }

  .legend-list {
    li {
      display: flex;
      align-items: center;
      color: #666;
      font-size: 12px;
      line-height: 24px;

      &:not(:last-child) {
        margin-bottom: 4px;
      }

      .rect {
        display: block;
        width: 11px;
        height: 2px;
        margin-right: 3px;
      }
    }
  }
}
</style>
